import React, { CSSProperties } from 'react';
import { message } from 'antd';
import BraftEditor, { EditorState } from 'braft-editor';
import 'braft-editor/dist/index.css';
import { FileGroup } from "common/utils/data";
import { completeImgUrl, ossDomain } from "common/utils/utils";
import SelectDataArticleModal from "@/components/Editor/SelectDataArticleModal";
// @ts-ignore
import { ContentUtils } from 'braft-utils';
import Iframe from "./Iframe";
import { fileV1ControllerCreateUploadToken } from "@/services/auto/file";
import axios from "axios";

function IframeEntityComponent(props: any) {
  // 这边getData()返回的是一个param object
  const data: { src: string } = props.contentState.getEntity(props.block.getEntityAt(0)).getData()
  return <Iframe src={data.src} />
}

function IframeBlockComponent(props: any) {
  // block.getData() 返回的只是一个伪Map，所以转换下
  const originalData = props.block.getData()
  return <Iframe src={originalData.get('src')} />
}

// TODO: BraftEditor 对 TS 支持还不是很完善，而且那边一般也是设为any，所以先默认为 any
// 后续可以考虑基于 BraftEditor 集成 ts，然后再完善类型
const blockRendererFn = (block: any, { editor, editorState }: any) => {
  // 上传 html 时触发
  if (block.getType() === 'atomic') {
    const entity = editorState.getCurrentContent().getEntity(block.getEntityAt(0))
    if (entity.getType() === 'entity-iframe') {
      return {
        component: IframeEntityComponent,
        editable: false, // 此处的editable并不代表组件内容实际可编辑
        props: { editor, editorState } // 此处传入的内容可以在组件中通过this.props.blockProps获取到
      }
    }
  }
  // 初始化数据时触发
  if (block.getType() === 'block-iframe') {
    return {
      component: IframeBlockComponent,
      editable: false,
      props: { editor, editorState }
    }
  }
  // 不满足block.getType() === 'block-iframe'的情况时请勿return任何内容以免造成其他类型的block显示异常
}

// 自定义block输入转换器，用于将符合规则的 iframe 转换成相应的block
const blockImportFn = (nodeName: string, node: HTMLElement) => {
  if (nodeName === 'iframe') {
    return {
      type: 'block-iframe',
      data: {
        src: (node as HTMLIFrameElement).src,
      }
    }
  }
}
// 自定义block输出转换器，用于将不同的block转换成不同的html内容
const blockExportFn = (contentState: any, block: any) => {
  // 上传的 html
  if (block.type === 'atomic') {
    if (block.entityRanges.length) {
      const entity = contentState.getEntity(contentState.getBlockForKey(block.key).getEntityAt(0))
      if (entity.getType() === 'entity-iframe') {
        const blockData = entity.getData()
        // 这里会把这个组件字符串话，不能组件形式，只能函数式
        return Iframe({src: blockData.src})
      }
    }
  }
  // 页面传入的 iframe
  if (block.type === 'block-iframe') {
    const { src } = block.data
    // 这里会把这个组件字符串话，不能组件形式，只能函数式
    return Iframe({src})
  }
}

interface Props {
  fileGroup: FileGroup;
  value?: EditorState;
  onChange?: (editorState: EditorState) => void;
  className?: string;
  controlBarClassName?: string;
  contentClassName?: string;
  onSave?: ()=>void;
  style?: CSSProperties;
}

export default function Editor(props: Props) {
  const {
    value,
    onChange,
    fileGroup,
    className,
    controlBarClassName,
    contentClassName,
    onSave,
    style,
  } = props;

 /* const {run: runPrefop} = useRequest((id: string, cb: ()=>void)=>`/qiniu-api/status/get/prefop?id=${id}`, {
    manual: true,
    fetchKey: id => id,
    onSuccess: ((res, [id, cb])=>{
      if(res.code === 0){
        cb();
      }else{
        setTimeout(()=> {
          runPrefop(id, cb);
        }, 1000);
      }
    })
  })*/

  return (
    <BraftEditor
      className={className}
      style={style}
      blockRendererFn={blockRendererFn}
      converts={{ blockImportFn, blockExportFn }}
      controlBarClassName={controlBarClassName}
      contentClassName={contentClassName}
      value={value}
      textBackgroundColor={false}
      media={{
        uploadFn: (param) => {
          fileV1ControllerCreateUploadToken({
            filename: param.file.name,
            group: fileGroup,
          }).then((res)=>{
            const formData = new FormData();
            formData.append('OSSAccessKeyId', res.OSSAccessKeyId);
            formData.append('policy', res.policy);
            formData.append('Signature', res.Signature);
            formData.append('key', res.key);
            formData.append('file', param.file);

            return axios.request({
              url: ossDomain,
              data: formData,
              method: 'POST',
              onUploadProgress: (e)=>{
                if(e.progress){
                  param.progress(e.progress);
                }

              }
            }).then(()=>{
              param.success({
                url: completeImgUrl(res.key)!,
                meta: {
                  id: res.key,
                  title: res.key,
                  alt: res.key,
                  poster: res.key,
                  loop: false,
                  autoPlay: false,
                  controls: false,
                },
              });
            })
          }).catch((err)=>{
            param.error({ msg: `上传失败，${err.message}` });
          })
        },
        validateFn: (file) => {
          if (file.size > 1024 * 1024 * 5) {
            message.error('图片大小须小于5M!');
            return false;
          }
          return true;
        },
        accepts: {
          image: 'image/png,image/jpeg,image/gif',
          video: false,
          audio: false,
        },
      }}
      onChange={(editorState)=>{
        if(value !== editorState){
          onChange?.(editorState);
        }
      }}
      onSave={onSave}
      extendControls={[
        'separator',
        {
          key: 'select-data-article-model',
          type: 'component',
          component: <SelectDataArticleModal onOk={(src)=>{
            onChange?.(ContentUtils.insertAtomicBlock(value,'entity-iframe',true,{
              src,
            } ));
          }} />
        },
      ]}
    />
  );
}
